define([
    'dojo/dom-construct',
    'esri/layers/Layer',
    this.path + '../4.x/plugins/esri/Windy.js',
], function (DomConstructUtils, Layer, Windy) {
    var RL = Layer.createSubclass({
        // "-chains-": {
        //     constructor: "manual"
        // },
        setData: function (mapView, layer) {
            var me = this;
            var options = layer.layer || {};
            this.options = Object.assign({ projection: 'EPSG:4326' }, options);
            me.mapView = mapView;
            var mapUtils = mapView.mapUtils;
            me.mapUtils = mapUtils;
            me.clickEvt = options.onClick;
            me.mouseMoveEvt = options.onMouseMove;
            this.options.minScale = options.minScale;
            this.options.maxScale = options.maxScale;

            this.options.particleScale =
                options.particleScale || (options.options && options.options.particleScale);
            var data = options.data || [];
            this.data = data;
            this.isClear = false;

            this.createCanvas();
            this.startMapEventListeners();

            if (options.url) {
                $.ajax({
                    url: options.url,
                    success: function (res) {
                        me.data = res;
                        if (me._canvas) {
                            renderWind.bind(me)(me.data);
                        }
                    },
                });
            } else {
                if (me._canvas) {
                    renderWind.bind(me)(data);
                }
            }

            function renderWind(data) {
                if (!me.$Wind) {
                    me.render(me._canvas);
                } else if (me.$Wind) {
                    const extent = me._getExtent();
                    me.$Wind.update(me.getData(), extent[0], extent[1], extent[2], extent[3]);
                }
            }

            return this;
        },
        constructor: function () {
            _this = this;
            // // Manually call superclass constructor with required arguments
            // this.inherited(arguments, ["http://some.server.com/path", options]);
            // _this = this;
            // this.options = Object.assign({projection: 'EPSG:4326'}, options);
            // this.loaded = true;
            // this.isClear = false
            // this.onLoad(this);
        },
        createCanvas: function () {
            let canvas = DomConstructUtils.create('canvas', {
                id: 'canvas',
                width: this.view.width + 'px',
                height: this.view.height + 'px',
                style: 'position: absolute; left: 0px; top: 0px;',
            });
            this._canvas = canvas;
            this._context = canvas.getContext('2d');
            if (!this._context) {
                console.error('This browser does not support <canvas> elements.');
            }
            let parent = this.view.canvas.parentElement;
            parent.appendChild(canvas);

            if (this.opacity) {
                this._canvas.style.opacity = this.opacity;
            }

            // Event connections
            // this._connects = [];
            // this._connects.push(connect.connect(map, "onPanStart", this, () => {
            //     element.style.display = 'none';
            // }));
            // this._connects.push(connect.connect(map, "onPanEnd", this, this.redraw));
            // this._connects.push(connect.connect(map, "onZoomStart", this, () => {
            //     element.style.display = 'none';
            // }));
            // this._connects.push(connect.connect(map, "onZoomEnd", this, this.redraw));
            // this._connects.push(connect.connect(map, "onExtentChange", this, this.redraw));
            // this._connects.push(connect.connect(this, "onVisibilityChange", this, this.redraw));
            // this._connects.push(connect.connect(map, "onClick", this, this._onClickHandler));
            // this._connects.push(connect.connect(map, "onMouseMove", this, this._onMouseMoveHandler));

            // return element;
        },
        startMapEventListeners: function () {
            var me = this;
            let view = this.view;
            this._watchExtent = view.watch('extent', function () {
                if (!me.visible) {
                    return;
                }
                me.redraw();
            });
        },
        // _unsetMap: function(map, container) {
        //     arrayUtils.forEach(this._connects, connect.disconnect, this);
        //     if (this._canvas) {
        //         container.removeChild(this._canvas);
        //     }
        //     this._map = this._canvas = this._context = this.data = this._connects = null;
        // },
        _elementVisible: true,
        allgrid: [],
        _windyIdentifyLayerName: 'windyPt',
        _calDetailInfo(evt) {
            var me = this;
            var mapUtils = me.mapUtils;
            mapUtils._currentClickLayer = me.id;

            var point = evt.mapPoint;
            point.lng =
                (evt.mapPoint.getLongitude && evt.mapPoint.getLongitude()) || evt.mapPoint.x;
            point.lat = (evt.mapPoint.getLatitude && evt.mapPoint.getLatitude()) || evt.mapPoint.y;
            if (!me.$Wind) {
                return;
            }
            var gridValue = me.$Wind.interpolatePoint(point.lng, point.lat);
            var result = {};

            if (gridValue && !isNaN(gridValue[0]) && !isNaN(gridValue[1])) {
                var uMs = gridValue[0];
                var vMs = gridValue[1];
                vMs = vMs > 0 ? (vMs = vMs - vMs * 2) : Math.abs(vMs);
                var temp = gridValue[2];

                result.angle = mapUtils.getWindyAngle(uMs, vMs);
                result.direction = mapUtils.getWindyDirection(result.angle);
                result.speed = mapUtils.getWindySpeed(uMs, vMs).toFixed(1);
                result.speedUtil = 'm/s';
                result.temp = '--';
                result.tempUtil = '';
                if (!isNaN(temp)) {
                    //result.temp = (temp - 273.15).toFixed(1);
                    result.temp = temp.toFixed(1);
                    result.tempUtil = '°C';
                }

                result.level = mapUtils.getWindyLevel(result.speed);
                result.levelUtil = '级';
            }
            var data = Object.assign({ x: point.x, y: point.y }, result);

            evt.graphic = {
                attributes: data,
                geometry: point,
            };
            me._event = evt;
            var e = {
                mapView: me.mapView,
                data: data,
                getLocation: me.getLocation.bind(me),
            };
            return e;
        },
        _onMouseMoveHandler(evt) {
            var me = this;
            if (Object.prototype.toString.call(me.mouseMoveEvt) == '[object Function]') {
                var e = me._calDetailInfo(evt);
                me.mouseMoveEvt(e);
            }
        },
        _onClickHandler(evt) {
            var me = this;

            if (Object.prototype.toString.call(this.clickEvt) == '[object Function]') {
                var e = me._calDetailInfo(evt);
                me.clickEvt(e);
            }
        },
        getLocation: function () {
            var esriEvent = this._event;
            var location = this.getGraphicLocation(this.mapView, esriEvent);
            location.event = esriEvent;
            return location;
        },
        getGraphicLocation: function (mapView, esriEvent) {
            if (!esriEvent || !esriEvent.graphic) {
                return;
            }
            if (!mapView) {
                return;
            }

            var map = mapView.getMap();
            if (!map) {
                return;
            }

            var geometry = esriEvent.graphic.geometry || {};
            var lngFieldName = mapView.getLngFieldName();
            var latFieldName = mapView.getLatFieldName();
            var location = {};
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            return location;
        },
        refresh: function () {
            if (!this._canDraw()) {
                return;
            }
        },
        clear: function () {
            if (!this._canDraw()) {
                return;
            }

            this._context.clearRect(0, 0, this._mapWidth, this._mapHeight);
        },
        _canDraw: function () {
            return this._map && this._canvas && this._context ? true : false;
        },
        _panHandler: function (extent, delta) {
            domStyle.set(this._canvas, { left: delta.x + 'px', top: delta.y + 'px' });
        },
        _extentChangeHandler: function (extent, delta, levelChange, lod) {
            if (!levelChange) {
                domStyle.set(this._canvas, { left: '0px', top: '0px' });
                this.clear();
            }
        },
        _visibilityChangeHandler: function (visible) {
            if (visible) {
                domUtils.show(this._canvas);
            } else {
                domUtils.hide(this._canvas);
            }
        },
        hide: function (e) {
            this.inherited(arguments);
            domUtils.hide(this._canvas);
        },
        show: function (e) {
            this.inherited(arguments);
            domUtils.show(this._canvas);
        },
        render: function () {
            const extent = this._getExtent();
            if (this._canvas && !this.$Wind) {
                this.$Wind = new Windy({
                    canvas: this._canvas,
                    data: this.data,
                    projection: this.options.projection,
                    windColors: this.options.windColors,
                    particleScale: this.options.particleScale,
                });

                this.$Wind.start(extent[0], extent[1], extent[2], extent[3]);
            } else if (this._canvas && this.$Wind) {
                this.$Wind.start(extent[0], extent[1], extent[2], extent[3]);
            }
            if (!this.visible) {
                return;
            }
            this.setScale(this.view, this._canvas);
        },
        _getExtent: function () {
            //by MHQ
            var extent = this.view.extent;
            let point = this.mapView.mapUtils.createPoint(this.mapView, {
                x: this.view.extent.xmin,
                y: this.view.extent.ymin,
            });
            let point2 = this.mapView.mapUtils.createPoint(this.mapView, {
                x: this.view.extent.xmax,
                y: this.view.extent.ymax,
            });

            let upperLeft = this.mapView.mapUtils.mapPointToScreen(this.mapView, point);
            let lowerRight = this.mapView.mapUtils.mapPointToScreen(this.mapView, point2);

            return [
                [
                    // [0, 0],
                    // [this.view.width, this.view.height]
                    // [upperLeft.x, upperLeft.y],
                    // [lowerRight.x, lowerRight.y]
                    [0, 0],
                    [this.view.width, this.view.height],
                    // [this.view.width, this.view.height]
                ],
                this.view.width,
                this.view.height,
                [
                    [extent.xmin, extent.ymin],
                    [extent.xmax, extent.ymax],
                ],
            ];
        },
        redraw() {
            if (!_this.$Wind) {
                return;
            }
            _this.$Wind.stop();
            if (!this.visible) {
                return;
            }
            this.setScale(this.view, _this._canvas);
            if (!this._elementVisible) {
                return;
            }
            _this._canvas.width = _this.view.width;
            _this._canvas.height = _this.view.height;
            const extent = _this._getExtent();

            setTimeout(function () {
                // let point = _this.mapView.mapUtils.createPoint(_this.mapView, { x: _this.view.extent.xmin, y: _this.view.extent.ymin })
                // let point2 = _this.mapView.mapUtils.createPoint(_this.mapView, { x: _this.view.extent.xmax, y: _this.view.extent.ymax })
                // console.log('aaa', _this.mapView.mapUtils.mapPointToScreen(_this.mapView, point));
                // console.log('aaa', _this.mapView.mapUtils.mapPointToScreen(_this.mapView, point2));
                // debugger
                _this.$Wind.start(extent[0], extent[1], extent[2], extent[3]);
            });
        },
        getData: function () {
            return this.data;
        },
        // getMap: function() {
        //     return _this.map
        // },
        clearWind() {
            const _map = _this.getMap();
            if (!_map) return;
            if (this.$Wind) this.$Wind.stop();
            this.isClear = true;
            this._cloneLayer = this;
            _map.removeLayer(this);
        },
        removeLayer: function () {
            const _map = _this.getMap();
            if (!_map) return;
            if (_this.$Wind) _this.$Wind.stop();
            if (_this._connects && _this._connects.length > 0) {
                _this._connects.map(function (item) {
                    item.remove();
                    item = null;
                });
            }
            _map.removeLayer(this);
            delete this._canvas;
            delete this.$Wind;
            delete this._cloneLayer;
        },
        setScale: function (view, _element) {
            var scale = view.scale;

            if (this.options && this.options.minScale && this.options.maxScale) {
                if (scale > this.options.minScale || scale < this.options.maxScale) {
                    _element.style.display = 'none';
                    this._elementVisible = false;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                }
            } else if (this.options && this.options.minScale > 0) {
                if (scale > this.options.minScale) {
                    _element.style.display = 'none';
                    this._elementVisible = false;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                }
            } else if (this.options && this.options.maxScale > 0) {
                if (scale < this.options.maxScale) {
                    _element.style.display = 'none';
                    this._elementVisible = false;
                } else {
                    _element.style.display = 'block';
                    this._elementVisible = true;
                }
            } else {
                _element.style.display = 'block';
                this._elementVisible = true;
            }
        },
    });

    return RL;
});
